package com.wallet.listener;

import com.alibaba.fastjson.JSON;
import com.rabbitmq.client.Channel;
import com.wallet.constants.BusinessConstants;
import com.wallet.constants.ConsumeWayConstants;
import com.wallet.constants.PayMethodConstants;
import com.wallet.entity.WalletEntity;
import com.wallet.entity.WalletDetailsEntity;
import com.wallet.service.WalletDetailsService;
import com.wallet.service.WalletService;
import com.wallet.util.R;
import com.wallet.vo.PayAsyncVo;
import org.redisson.api.RLock;
import org.redisson.api.RReadWriteLock;
import org.redisson.api.RedissonClient;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.io.IOException;
import java.math.BigDecimal;
import java.util.Date;

/**
 * 退款队列监听器
 * @author zhangguangyuang
 */
@Component
@RabbitListener(queues = "wallet.refund.wallet.queue")
public class OrderRefundListener {
    @Autowired
    private StringRedisTemplate redisTemplate;

    @Autowired
    private RedissonClient redissonClient;

    @Autowired
    private WalletService walletService;

    @Autowired
    private WalletDetailsService walletDetailsService;

    //退款订单号key
    private String REFUND_CHARE_PREFIX="refund:orderNo";

    @Transactional
    @RabbitHandler
    public void listener(PayAsyncVo payAsyncVo, Channel channel, Message message) throws IOException{
        System.out.println("收到退款信息，准备增加钱包流水信息"+payAsyncVo.getOrderNo());
        //增加读写锁，防止其他线程写入重复数据
        RReadWriteLock readWriteLock = redissonClient.getReadWriteLock(BusinessConstants.WALLET_READ_WRITE_LOCK_PREFIX+payAsyncVo.getWalletId());
        RLock rLock = readWriteLock.readLock();
        try{
            //判断订单号是否已存在
            if(!redisTemplate.opsForHash().hasKey(REFUND_CHARE_PREFIX,payAsyncVo.getOrderNo())){
                //TODO 判断支付方式
                if(PayMethodConstants.PAY_METHOD_WALLET.equals(payAsyncVo.getPayMethod())){
                    Boolean isExist = walletDetailsService.isExistOrderNoAndTradeNo(payAsyncVo.getOrderNo(),payAsyncVo.getOutTradeNo());
                    if(!isExist){
                        // 退款到钱包
                        WalletEntity wallet = new WalletEntity();
                        wallet.setUserId(payAsyncVo.getUserId());
                        wallet.setMoney(new BigDecimal(payAsyncVo.getDecreaseMoney()));
                        walletService.refundToWallet(wallet);
                        WalletEntity w = walletService.getMoneyAndIdByUserId(payAsyncVo.getUserId());
                        WalletDetailsEntity walletDetails = new WalletDetailsEntity();
                        walletDetails.setWalletId(payAsyncVo.getWalletId());
                        walletDetails.setWalletMoney(w.getMoney());
                        walletDetails.setMoney(wallet.getMoney());
                        walletDetails.setAddOrSub(BusinessConstants.WALLET_ADD);
                        walletDetails.setConsumeWay(ConsumeWayConstants.REFUND);
                        walletDetails.setOrderNo(payAsyncVo.getOrderNo());
                        walletDetails.setOutTradeNo(payAsyncVo.getOutTradeNo());
                        walletDetails.setRemarks("退款成功");
                        walletDetails.setDeleted(0);
                        walletDetails.setCreateTime(new Date());
                        walletDetails.setUpdateTime(new Date());
                        //TODO 商品库存退回
                        walletDetailsService.save(walletDetails);
                        String result = JSON.toJSONString(R.ok().put("data", "退款到钱包成功"));
                        redisTemplate.opsForHash().put(REFUND_CHARE_PREFIX,payAsyncVo.getOrderNo(),result);
                        redisTemplate.opsForHash().delete(BusinessConstants.WALLET_DETAILS_PREFIX,String.valueOf(payAsyncVo.getWalletId()));
                        channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);
                    }else{
                        //处理过此记录，直接从消息队列删除
                        String result = JSON.toJSONString(R.error(12,"退款已完成，不能重复付款"));
                        redisTemplate.opsForHash().put(REFUND_CHARE_PREFIX,payAsyncVo.getOutTradeNo(),result);
                        channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);
                    }
                }else{
                    //TODO 调用银行卡退款的service
                    //TODO 商品库存退回
                    String result = JSON.toJSONString(R.ok().put("data", "退款到银行卡成功"));
                    redisTemplate.opsForHash().put(REFUND_CHARE_PREFIX,payAsyncVo.getOrderNo(),result);
                    redisTemplate.opsForHash().delete(BusinessConstants.WALLET_DETAILS_PREFIX,String.valueOf(payAsyncVo.getWalletId()));
                    channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);
                }
            }else{
                //此退款信息已存在
                String result = JSON.toJSONString(R.error(12,"退款已完成，不能重复退款"));
                redisTemplate.opsForHash().put(REFUND_CHARE_PREFIX,payAsyncVo.getOrderNo(),result);
                channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);
            }
        }catch (Exception e){
            channel.basicReject(message.getMessageProperties().getDeliveryTag(),true);
        }finally {
            rLock.unlock();
        }

    }
}
